home *** CD-ROM | disk | FTP | other *** search
- /*
-
- demo.cpp
- 12-6-90
- FlexList tutorial
-
- Copyright 1990
- John W. Small
- All rights reserved
-
- PSW / Power SoftWare
- P.O. Box 10072
- McLean, Virginia 22102 8072
- (703) 759-3838
-
- This program was written to be compiled with the
- Turbo C++ compiler under the MS DOS operating
- system. To port to another environment rewrite
- PressEnter() to pause for the user and then clear
- the screen. Rand() should be available in some
- form on your system. Gets(), used for string input,
- may also have to be replaced. That should do the
- trick. I would have used "cin", however it proved
- to be inadequate. I/O streams are for C++ 2.0.
-
- */
-
- #include <stdio.h> // getchar(), gets()
- #include <stdlib.h> // rand()
- #include <dos.h> // int86(): to clear screen
-
- #include <iostream.h> // cout
- #include <iomanip.h> // setw()
- #include <flexlist.hpp>
-
- int ints[] = { 1,2,3,4,5,6,7,8,9,10 };
- int i, r, *rptr, *iptr;
- char line[81];
-
- int CompareIntegers(void *int1, void *int2)
- {
- return (*(int *)int1 - *(int *)int2);
- }
-
- void PressEnter(char *msg = "\n\nPress 'Enter' to continue ...")
- {
- union REGS rgs;
- cout << msg;
- getchar();
- rgs.h.ah = 2; // gotoxy(1,1);
- rgs.x.dx = 0;
- rgs.h.bh = 0;
- int86(0x10,&rgs,&rgs);
- rgs.h.ah = 9; // clear screen
- rgs.h.al = ' ';
- rgs.x.bx = 0x0007;
- rgs.x.cx = 80 * 25; // screen dimensions
- int86(0x10,&rgs,&rgs);
- }
-
- main()
- {
- cout << "\nIt's best to have a printed copy of flexlist.hpp to read along with.";
- cout << "\n\nAnytime your C++ application requires a stack, queue, or linked";
- cout << "\nlist, simply include <flexlist.hpp>. Next define your stack, queue,";
- cout << "\nor list as a variable of type FlexList. The FlexList class is";
- cout << "\nreally a generic hybrid stack-queue-list-array data structure.";
- cout << "\nYour FlexList can be initialized to store any type of data.";
- cout << "\n\nFor example:";
- cout << "\n\n FlexList Q(sizeof(int));";
- cout << "\n\nIn the above example any type, struct or class, can be used";
- cout << "\nin place of int.";
- PressEnter();
- cout << "\nThe FlexList class has over 30 functions for accessing your list as a stack";
- cout << "\nqueue, list, or an array interchangeably! You can push, pop, insert";
- cout << "\ndelete, sort, store, recall, or find, to name but just a few";
- cout << "\noperations. The complement of FlexList methods allows you";
- cout << "\nto access your list's data by value (copy) or by reference (pointer),";
- cout << "\nas well as to move nodes directly between lists.";
- cout << "\n\nConsider the following code segment.";
- cout << "\n\n // Insert 10 random integers into a queue. ";
- cout << "\n\n for (i = 0; i < 10; i++) {";
- cout << "\n r = rand();";
- cout << "\n cout << setw(7) << r;";
- cout << "\n Q.insQD(&r) // insert r into queue";
- cout << "\n }";
- PressEnter("\n\nPress 'Enter' to execute the above code segment.");
- cout << "\n";
- FlexList Q(sizeof(r));
- for (i = 0; i < 10; i++) {
- r = rand();
- cout << setw(7) << r;
- Q.insQD(&r);
- }
- PressEnter();
- cout << "\nNext, consider this code segment: ";
- cout << "\n\n int CompareIntegers(void *int1, void *int2)";
- cout << "\n {";
- cout << "\n return (*(int *)int1 - *(int *)int2)";
- cout << "\n }";
- cout << "\n\n // Sort the queue and pop the results.";
- cout << "\n\n Q.sort(FLcomparE(CompareIntegers));";
- cout << "\n while (Q.nextD(&r)) cout << setw(7) << r;";
- PressEnter("\n\nPress 'Enter' again to execute this code.");
- cout << "\nFirst the random integers again ...\n\n";
- while (Q.nextD(&r)) cout << setw(7) << r;
- cout << "\n\nAnd the sorted results ...\n\n";
- Q.sort(FLcomparE(CompareIntegers));
- Q.mkcur();
- while (Q.nextD(&r)) cout << setw(7) << r;
- cout << "\n\nFlexList methods that perform sorts or searches use a function";
- cout << "\npointer to a compare function. Your compare function";
- cout << "\ndecides which fields in your data to compare!";
- PressEnter();
- cout << "\nMany FlexList methods return void pointers which can be considered";
- cout << "\nboolean values indicating the success or failure of the method at";
- cout << "\nhand. When such a method is successful, it returns a pointer to";
- cout << "\nyour data in the FlexNode in focus. In the last example 'nextD()'";
- cout << "\nwas used to read across the queue. Its return value is a void";
- cout << "\npointer. After the last FlexNode in the queue, 0 was returned";
- cout << "\nthereby terminating the loop. Let's read across that queue again";
- cout << "\nbut this time using pointers to the data instead of copying them.";
- cout << "\n\n int *rptr;";
- cout << "\n while ((rptr = (int *) Q.nextD()) != 0) cout << setw(7) << *rptr;\n\n";
- while ((rptr = (int *) Q.nextD()) != 0) cout << setw(7) << *rptr;
- PressEnter();
- cout << "\nWhen accessing/modifying FlexNodes containing large data structures";
- cout << "\nthis approach will usually prove vastly more efficient than copying";
- cout << "\nthe data of each node twice. It's important also to notice that the";
- cout << "\nnextD() declaration provides a default for its one parameter thus";
- cout << "\nallowing its invocation without an actual parameter. With methods";
- cout << "\nthat copy data to/from FlexNodes, an address of 0 will prevent";
- cout << "\nthe method in question from copying data. The method will carry";
- cout << "\nout its operation otherwise unchanged, however. NextD()'s default";
- cout << "\nis zero, so it didn't copy any data, but it still advanced to the";
- cout << "\nnext FlexNode and returned a pointer to its data.";
- PressEnter();
- cout << "\nThe FlexList methods ending in 'N' operate on FlexNodes instead of";
- cout << "\nthe data in the nodes. These come in handy when you are writing queuing";
- cout << "\nnetwork simulations and the like, where you want to be constantly moving";
- cout << "\nnodes between queues. A multitasking OS simulation is a good example";
- cout << "\nwhere you move PCBs (process control blocks) between the run, ready,";
- cout << "\nblocked, and swapped out queues. Let's see, that last queue with 10";
- cout << "\nintegers is still in memory, we'll work on that one. Consider the";
- cout << "\nfollowing code ...";
- cout << "\n\n FlexList S(Q.SizeofNodeData())";
- cout << "\n while (S.pushN(Q.popN()));";
- cout << "\n while (S.prev(&r)) cout << setw(7) << r;";
- cout << "\n\nAnd the results ...\n\n";
- FlexList S(Q.SizeofNodeData());
- while (Q.Nodes()) S.pushN(Q.popN());
- while (S.prevD(&r)) cout << setw(7) << r;
- Q.clear();
- cout << "\n\nWow! We popped one stack into the other. That should have reversed the";
- cout << "\norder. But wait, we then read the list backward with the prevD() method.";
- cout << "\nThat's right, everything's okay.";
- PressEnter();
- cout << "\nIf you were really watching closely during the last few examples, you";
- cout << "\nprobably wondered about how prevD() and nextD() knew where in the list";
- cout << "\nthey were. All FlexLists maintain a pointer to the current node. Stack";
- cout << "\nand queue methods don't disturb this setting. If the current is popped,";
- cout << "\nhowever, the current node becomes undefined just as it is after FlexList";
- cout << "\ninitialization. NextD() and prevD() 'walk' the current pointer across the";
- cout << "\nlist, making the current become undefined once each cycle at which time";
- cout << "\nthese methods return 0. This is how I was able to control looping ";
- cout << "\nthrough the lists in the previous examples. Array access methods, i.e.";
- cout << "\nstoreD and recallD, set the current pointer to the last node accessed.";
- cout << "\nThe next array access first determines whether the front, current, or";
- cout << "\nrear pointer is closest to the requested node and then traverses from";
- cout << "\nthe closest pointer across the links to the requested node, making it the";
- cout << "\nnew current node. Both methods call the mkcur() method to perform this";
- cout << "\noperation. The insD() method inserts after the current node making the";
- cout << "\nnew node current, while delD(), deletes the current node making the";
- cout << "\nprevious node current.";
- PressEnter();
- cout << "\nLet's take a look at a FlexList's array access methods. You will";
- cout << "\nrecall that the S stack of integers is still in memory.";
- cout << "\nThe following code will now be executed:";
- cout << "\n\n for(i = 1; S.recallD(&r,i); i++)";
- cout << "\n cout << setw(7) << r;";
- cout << "\n\nAnd the results ...\n\n";
- for (i = 1; S.recallD(&r,i); i++)
- cout << setw(7) << r;
- S.clear();
- PressEnter();
- cout << "\nLet's see insD() and delD() in action and this time with something other";
- cout << "\nthan integers! Consider the following code and then start your input.";
- cout << "\n\n char line[81];";
- cout << "\n FlexList s(FLstrings);";
- cout << "\n while (s.Nodes() < 3) {";
- cout << "\n cout << \"\\nEnter string: \"; gets(line);";
- cout << "\n s.insD(line);";
- cout << "\n }\n\n";
- FlexList s(FLstrings);
- while (s.Nodes() < 3) {
- cout << "Enter string: ";
- gets(line);
- s.insD(line);
- }
- PressEnter();
- cout << "\n\nThe last node is now the current one and we'll start deleting them.";
- cout << "\nSince deleting makes the previous node the new current node, successive";
- cout << "\ndeletes will walk across the list from the rear to the front.";
- cout << "\nThe following code will now be executed.";
- cout << "\n\n while (s.delD(line)) cout << \"\\n\" << line;\n";
- while (s.delD(line)) cout << "\n" << line;
- cout << "\n\nThis FlexList of strings is an example of a heterogeneous FlexList.";
- cout << "\nThe FlexNodes were only as big as the strings held within.";
- cout << "\nSee the first FlexList constructor entry in the reference chapter for";
- cout << "\ninformation on deriving your own heterogeneous FlexLists.";
- cout << "\nFlexlist.cpp's comments also explain what is going on.";
- PressEnter();
- cout << "\nSometimes you want to work with a list, other times it's more convenient";
- cout << "\nto work with an array. Although Flexlist allows this chameleon behavior,";
- cout << "\nyour application may progress in stages that favor a list at one point";
- cout << "\nand an array at another. FlexList has methods for converting a";
- cout << "\nconventional array into a FlexList or a FlexList into a dynamic array";
- cout << "\nthus allowing you to optimize the performance of your application.";
- cout << "\nYou can think of the FlexList constructor with array parameters, as";
- cout << "\nexploding a conventional array into a FlexList. For example:";
- cout << "\n\n int ints[] = { 1,2,3,4,5,6,7,8,9,10 };";
- cout << "\n FlexList A(sizeof(int),10,ints);";
- cout << "\n while (A.nextD(&i)) cout << setw(7) << i;";
- cout << "\n\nAnd the results of its execution ...\n\n";
- FlexList A(sizeof(int),10,ints);
- while (A.nextD(&i)) cout << setw(7) << i;
- PressEnter();
- cout << "\nThink of the FlexList method, pack(), as imploding a FlexList into a";
- cout << "\ndynamic array. Consider the following code and the previous list.";
- cout << "\n\n int *iptr = A.pack();";
- cout << "\n for (i = 0; i < 10; i++)";
- cout << "\n cout << setw(7) << iptr[i];";
- cout << "\n\nAnd the results of its execution ...\n\n";
- iptr = (int *) A.pack();
- for (i = 0; i < 10; i++)
- cout << setw(7) << iptr[i];
- delete iptr; A.clear();
- cout << "\n\nThe FlexList method, packPtrs, simply creates a 0 terminated array of";
- cout << "\npacked pointers which point to the data areas of all the FlexNodes.";
- cout << "\nDo you remember how FlexList methods returning void pointers worked?";
- cout << "\nThese are the same pointers all packed into a dynamic array. You can";
- cout << "\nquickly zip around a FlexList's nodes using these pointers to modify data.";
- cout << "\nWhen your application is finished this phase of processing it discards";
- cout << "\nthe array of pointers.";
- PressEnter();
- cout << "\nSince FlexList is a class, you can derive your own classes from it.";
- cout << "\nWhy would you want too? Suppose that you need a place to store data";
- cout << "\npertaining to the whole list? You can declare a new class, derived";
- cout << "\nfrom FlexList, that contains variables for this data. Thus you can";
- cout << "\nstore data associated with the list, in the list! Derived classes can";
- cout << "\nalso be made to store heterogeneous data in the FlexNodes via a";
- cout << "\nFlexList's virtual function hooks. These virtual functions are defined";
- cout << "\nthe FlexList base class to handle strings as you saw previously. Any-";
- cout << "\ntime a FlexList is constructed for data the size of zero the virtual";
- cout << "\nfunctions are turned on to create and destroy FlexNodes as well as";
- cout << "\ncopying the variant length data.";
- cout << "\n\nYour application's code size won't continue to grow when you add new";
- cout << "\ntypes of lists either, since FlexList is generic, it is able to store";
- cout << "\nany type of data, struct or class. And with the virtual overide feature";
- cout << "\nenabled in derived classes, almost any type of heterogeneous data can be";
- cout << "\naccommodated. Since FlexLists are initialized at";
- cout << "\nrun time, the data they hold or even their creation can be specified";
- cout << "\nat run time thus allowing your application new dimensions of adaptibility";
- cout << "\nto user specifications. And with FlexList you can quickly construct";
- cout << "\nlists of lists or other composite structures. FlexList will save you";
- cout << "\nhours of coding time, code space, money and headaches!";
- PressEnter();
- cout << "\n\nCopyright 1990, John W. Small, All right reserved";
- cout << "\n\nPSW / Power SoftWare";
- cout << "\nP.O. Box 10072";
- cout << "\nMcLean, Virginia 22102 8072";
- cout << "\n(703) 759-3838";
- cout << "\n\nRegister FlexList for $79.95 and get the";
- cout << "\ncomplete picture.";
- }
-